using System;
using System.Reflection;
using System.Collections.Generic;
using System.Globalization;

namespace Framework
{
	/// <summary>
	/// Summary description for ReflectUtil.
	/// </summary>
	public static class ReflectUtil
	{
		

		public static readonly string SPLIT_TYPE_DELIM = ",";

		public const BindingFlags BF_PUB_STA_IGNORECASE = BindingFlags.IgnoreCase | BindingFlags.Public | BindingFlags.Static;

		public const BindingFlags BF_ANY_PROP_FIELD = BindingFlags.IgnoreCase | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static;

        public const BindingFlags BF_ANY_PUBLIC_PROP_FIELD = BindingFlags.IgnoreCase | BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static;

        public const BindingFlags BF_ANY_METHOD_STATIC = BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic;

        public const BindingFlags BF_ANY_METHOD_INSTANCE = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;

		#region Split Assembly & Type
		/// <summary>
		/// Takes incoming full type string, defined as:
		/// "My.Namespace.MyType, My.Namespace, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" or 
		/// "My.Namespace.MyType, My.Namespace"
		///  And splits the type into two strings, the typeName and assemblyName.  Those are passed by as OUT params
		///  This routine also cleans up any extra whitespace, and throws an exception if the full type string
		///  does not have five comma-delimited parts....it expect the true full name complete with version and publickeytoken
		/// </summary>
		/// <param name="fullType"></param>
		/// <param name="typeName"></param>
		/// <param name="assemblyName"></param>
		private static void SplitType(string fullType, out string typeName, out string assemblyName)
		{
			string[] parts = fullType.Split(SPLIT_TYPE_DELIM.ToCharArray());

			if (parts.Length == 2)
			{
				typeName = parts[0].Trim();
				assemblyName = parts[1].Trim();
			}
			else if (parts.Length == 5)
			{
				typeName = parts[0].Trim();
				assemblyName = String.Concat(new[] 
               {
                  parts[1].Trim(), SPLIT_TYPE_DELIM,
                  parts[2].Trim(), SPLIT_TYPE_DELIM,
                  parts[3].Trim(), SPLIT_TYPE_DELIM,
                  parts[4].Trim() 
               });
			}
			else
			{
				throw new ArgumentException("FullType must be a comma seperated (TypeName, AssemblyName) or (TypeName, AssemblyName, Version, Culture, PublicKeyToken)\nFullType: " + fullType);
			}
		}
		#endregion

		#region Create Instance
		private static void ThrowCreateInstanceException(Exception ex, string typeName, string assemblyName, object[] constructorArgs, OnException onException)
		{
			if (onException == OnException.Throw)
			{
                var newEx = new Exception("Failed to create object instance.", ex);

                newEx.Data.Add("TypeName", typeName);
				newEx.Data.Add("AssemblyName", assemblyName);
				newEx.Data.Add("ConstructorArgs", constructorArgs);

                throw newEx;
			}
		}

		public static object CreateInstance(string fullTypeName)
		{
			return CreateInstance(fullTypeName, OnException.Ignore);
		}
        
		public static object CreateInstance(string fullTypeName, OnException onException)
		{
			string typeName;
			string assemblyName;

			SplitType(fullTypeName, out typeName, out assemblyName);

			return CreateInstance(typeName, assemblyName, onException);
		}

		public static object CreateInstance(string typeName, string assemblyName)
		{
			return CreateInstance(typeName, assemblyName, OnException.Ignore);
		}


		public static object CreateInstance(string typeName, string assemblyName, OnException onException)
		{
			object result = null;

			try
			{
				Assembly assembly = Assembly.Load(assemblyName);
				Type type = assembly.GetType(typeName, true, false);

				result = Activator.CreateInstance(type);
			}
			catch (Exception ex)
			{
				//Logger.Error( ex );

				ThrowCreateInstanceException(ex, typeName, assemblyName, null, onException);
			}

			if (result == null)
			{
				// I have know idea why this happens, but I have seen the Activator return null rather then throw an exception.
				ThrowCreateInstanceException(null, typeName, assemblyName, null, onException);
			}

			return result;
		}

		public static object CreateInstance(string typeName, string assemblyName, object[] constructorArgs)
		{
			return CreateInstance(typeName, assemblyName, constructorArgs, OnException.Ignore);
		}

		public static object CreateInstance(string typeName, string assemblyName, object[] constructorArgs, OnException onException)
		{
			try
			{
				Assembly assembly = Assembly.Load(assemblyName);
				Type type = assembly.GetType(typeName, true, false);

				return Activator.CreateInstance(type, constructorArgs);
			}
			catch (Exception ex)
			{
				//Logger.Error( ex );

				ThrowCreateInstanceException(ex, typeName, assemblyName, constructorArgs, onException);
			}
			return null;
		}


        public static T CreateInstance<T>()
        {
            return (T)CreateInstance(typeof(T), OnException.Ignore);
        }

		public static object CreateInstance(Type type)
		{
			return CreateInstance(type, OnException.Ignore);
		}

        public static T CreateInstance<T>(OnException onException)
        {
            return (T)CreateInstance(typeof(T), onException);
        }

		public static object CreateInstance(Type type, OnException onException)
		{
			try
			{
				return Activator.CreateInstance(type);
			}
			catch (Exception ex)
			{
				//Logger.Error(ex);

				if (onException == OnException.Throw)
				{
                    var newEx = new Exception("CreateInstance", ex);

                    newEx.Data.Add("type", type);

                    throw newEx;
				}
			}
			return null;
		}

		public static object CreateInstance(Type type, object[] constructorArgs)
		{
			return CreateInstance(type, constructorArgs, OnException.Ignore);
		}

		public static object CreateInstance(Type type, object[] constructorArgs, OnException onException)
		{
			try
			{
				return Activator.CreateInstance(type, constructorArgs);
			}
			catch (Exception ex)
			{
				//Logger.Error(ex);

				if (onException == OnException.Throw)
				{
                    var newEx = new Exception("CreateInstance", ex);

                    newEx.Data.Add("Type", type);
                    newEx.Data.Add("ConstructorArgs", constructorArgs);

                    throw newEx;
				}
			}
			return null;
		}
		#endregion

		#region GetType
		public static Type GetType(string fullTypeName)
		{
			return GetType(fullTypeName, OnException.Ignore);
		}

		public static Type GetType(string fullTypeName, OnException onException)
		{
			string typeName;
			string assemblyName;

			SplitType(fullTypeName, out typeName, out assemblyName);

			return GetType(typeName, assemblyName, onException);
		}

		public static Type GetType(string typeName, string assemblyName)
		{
			return GetType(typeName, assemblyName, OnException.Ignore);
		}

		public static Type GetType(string typeName, string assemblyName, OnException onException)
		{
			try
			{
				return Assembly.Load(assemblyName).GetType(typeName, true, false);
			}
			catch (Exception ex)
			{
				LogUtil.Error("ReflectUtil.GetType", ex);

				if (onException == OnException.Throw)
				{
					throw;
				}
			}
			return null;
		}
		#endregion

        #region GetTypesAsList
        public static List<Type> GetTypesAsList(List<string> typeList)
        {
            var result = new List<Type>();

            typeList.ForEach(typeName => result.Add(GetType(typeName)));

            return result;
        } 
        #endregion

		#region ToFullTypeName
		public static string ToFullTypeName(Type type)
		{
			return type.FullName + ", " + type.Assembly;
		}
		#endregion

		#region Type Conversion
		/// <summary>
		/// Converts the source object to an object of the destination type
		/// </summary>
		/// <param name="source">object to convert</param>
		/// <param name="destType">destination type for the conversion</param>
		/// <returns>the object converted or null if the conversion can't be done</returns>
		public static object ConvertTypes(object source, Type destType)
		{
			var sourceType = source.GetType();

			if (sourceType.Equals(typeof(string)))
			{
				var method = destType.GetMethod("Parse", BF_PUB_STA_IGNORECASE, null, new[] { typeof(string) }, null);

				if ((method != null) && (method.ReturnType.Equals(destType)))
				{
					return method.Invoke(null, BindingFlags.InvokeMethod, null, new[] { source }, CultureInfo.CurrentCulture);
				}
			}

			return null;   // Failed to convert
		}

		#endregion

		#region GetFieldValue
        /// <summary>
        /// Gets the non public field value from the instance
        /// </summary>
        /// <param name="instance">The instance.</param>
        /// <param name="fieldName">the name of the private field</param>
        /// <returns>field as the object</returns>
		public static object GetFieldValue(object instance, string fieldName)
		{
			var type = instance.GetType();
		    var field = type.GetField(fieldName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);

			return field.GetValue(instance);
		}

		/// <summary>
		/// Gets the non public field value of a specific type from the instance
		/// </summary>
		/// <param name="instance">the object containing the field</param>
		/// <param name="fieldName"> the name of the private field</param>
		/// <param name="type">the type of the field eg: ImageList</param>
		/// <returns>field as the object</returns>
		/// <remarks>This is good for any container/component controls like image list that are not seen in the design of the UI of the class</remarks> 
		public static object GetFieldValue(object instance, string fieldName, Type type)
		{
		    var field = type.GetField(fieldName, BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public);
			
            return field.GetValue(instance);
		}
		#endregion

        #region GetPropertyValueIfType
        /// <summary>
        /// Get value of a property
        /// </summary>
        /// <param name="property">The property.</param>
        /// <param name="obj">The obj.</param>
        /// <returns></returns>
        public static T GetPropertyValueIfType<T>(PropertyInfo property, object obj) where T : class 
        {
            if (property.PropertyType == typeof(T))
            {
                return GetPropertyValue(property, obj) as T;
            }

            return null;
        }
        #endregion

        #region GetPropertyValue
        /// <summary>
        /// Get value of a property
        /// </summary>
        /// <param name="property">The property.</param>
        /// <param name="obj">The obj.</param>
        /// <returns></returns>
        public static object GetPropertyValue(PropertyInfo property, object obj)
        {
            return property != null ? property.GetValue(obj, null) : null;
        }

        /// <summary>
        /// Get value of a property
        /// </summary>
        /// <param name="obj">source object</param>
        /// <param name="member">property or field to get</param>
        /// <returns>desired property or field (or null if it hasn't been found)</returns>
        public static object GetPropertyValue(object obj, string member)
        {
            return GetPropertyValue(obj, member, BF_ANY_PROP_FIELD);
        }

        /// <summary>
        /// Get value of a property
        /// </summary>
        /// <param name="obj">source object</param>
        /// <param name="member">property or field to get</param>
        /// <param name="flags">Binding flags</param>
        /// <returns>desired property or field (or null if it hasn't been found)</returns>
        public static object GetPropertyValue(object obj, string member, BindingFlags flags)
        {
            var objType = obj.GetType();

            var property = objType.GetProperty(member, flags);

            return GetPropertyValue(property, obj);
        }
        #endregion

        #region SetPropertyValue
        /// <summary>Set a property value</summary>
        /// <param name="obj">source object</param>
        /// <param name="member">property or field to set</param>
        /// <param name="value">value of the property or field</param>
        /// <returns>true if success, otherwise false</returns>
        public static bool SetPropertyValue(object obj, string member, object value)
        {
            return SetPropertyValue(obj, member, value, BF_ANY_PROP_FIELD);
        }
        /// <summary>Set a property value</summary>
        /// <param name="obj">source object</param>
        /// <param name="member">property or field to set</param>
        /// <param name="value">value of the property or field</param>
        /// <param name="flags">Binding flags</param>
        /// <returns>true if success, otherwise false</returns>
        public static bool SetPropertyValue(object obj, string member, object value, BindingFlags flags)
        {
            // search a property with that name
            var property = obj.GetType().GetProperty(member, flags);

            return SetPropertyValue(property, obj, value);
        }

        /// <summary>
        /// Set a property value
        /// </summary>
        /// <param name="property">The property.</param>
        /// <param name="obj">source object</param>
        /// <param name="value">value of the property or field</param>
        /// <returns>
        /// true if success, otherwise false
        /// </returns>
	    public static bool SetPropertyValue(PropertyInfo property, object obj, object value)
        {
            if (property != null)
            {
                property.SetValue(obj, value, null);

                return true;
            }

            return false;
        }
        #endregion

		#region GetPropertyOrFieldValue
		/// <summary>
		/// Get value of a property or field
		/// </summary>
		/// <param name="obj">source object</param>
		/// <param name="member">property or field to get</param>
		/// <returns>desired property or field (or null if it hasn't been found)</returns>
		public static object GetPropertyOrFieldValue(object obj, string member)
		{
			return GetPropertyOrFieldValue(obj, member, BF_ANY_PROP_FIELD);
		}

		/// <summary>
		/// Get value of a property or field
		/// </summary>
		/// <param name="obj">source object</param>
		/// <param name="member">property or field to get</param>
		/// <param name="flags">Binding flags</param>
		/// <returns>desired property or field (or null if it hasn't been found)</returns>
		public static object GetPropertyOrFieldValue(object obj, string member, BindingFlags flags)
		{
			var objType = obj.GetType();

			var prop = objType.GetProperty(member, flags);

			if (prop != null)
			{
				return prop.GetValue(obj, null);
			}

			// Property not found, try field
			var field = objType.GetField(member, flags);

			return (field == null) ? null : field.GetValue(obj);
		}
		#endregion

		#region GetPropertyOrFieldValue<T>
		/// <summary>
		/// Get value of a property or field
		/// </summary>
		/// <param name="obj">source object</param>
		/// <param name="member">property or field to get</param>
		/// <returns>desired property or field (or null if it hasn't been found)</returns>
		public static T GetPropertyOrFieldValue<T>(object obj, string member)
		{
			return (T)GetPropertyOrFieldValue(obj, member, BF_ANY_PROP_FIELD);
		}
		#endregion

        #region GetPropertyOrFieldValueStatic
        /// <summary>
        /// Get value of a property or field
        /// </summary>
        /// <param name="type">The type.</param>
        /// <param name="member">property or field to get</param>
        /// <returns>
        /// desired property or field (or null if it hasn't been found)
        /// </returns>
        public static object GetPropertyOrFieldValueStatic(Type type, string member)
        {
            return GetPropertyOrFieldValueStatic(type, member, BF_ANY_PROP_FIELD);
        }

        /// <summary>
        /// Get value of a property or field
        /// </summary>
        /// <param name="type">The type.</param>
        /// <param name="member">property or field to get</param>
        /// <param name="flags">Binding flags</param>
        /// <returns>
        /// desired property or field (or null if it hasn't been found)
        /// </returns>
        public static object GetPropertyOrFieldValueStatic(Type type, string member, BindingFlags flags)
        {
            var prop = type.GetProperty(member, flags);

            if (prop != null)
            {
                return prop.GetValue(null, null);
            }

            // Property not found, try field
            var field = type.GetField(member, flags);

            return (field == null) ? null : field.GetValue(null);
        }
        #endregion

        #region GetPropertyOrFieldValueStatic<T>
        /// <summary>
        /// Get value of a property or field
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="type">The type.</param>
        /// <param name="member">property or field to get</param>
        /// <returns>
        /// desired property or field (or null if it hasn't been found)
        /// </returns>
        public static T GetPropertyOrFieldValueStatic<T>(Type type, string member)
        {
            return (T)GetPropertyOrFieldValueStatic(type, member, BF_ANY_PROP_FIELD);
        }
        #endregion

		#region GetPropertyOrFieldType
		/// <summary>
		/// Get value of a property or field type
		/// </summary>
		/// <param name="obj">source object</param>
		/// <param name="member">property or field to get</param>
		/// <returns>property or field type (or null if not found)</returns>
		public static Type GetPropertyOrFieldType(object obj, string member)
		{
			return GetPropertyOrFieldType(obj, member, BF_ANY_PROP_FIELD);
		}

		/// <summary>
		/// Get value of a property or field type
		/// </summary>
		/// <param name="obj">source object</param>
		/// <param name="member">property or field to get</param>
		/// <param name="flags">Binding flags</param>
		/// <returns>property or field type (or null if not found)</returns>
		public static Type GetPropertyOrFieldType(object obj, string member, BindingFlags flags)
		{
			var objType = obj.GetType();

			var prop = objType.GetProperty(member, flags);

			if (prop != null)
			{
				return prop.PropertyType;
			}

			// Property not found, try field
			var field = objType.GetField(member, flags);

			return (field == null) ? null : field.FieldType;
		}
		#endregion

		#region SetPropertyOrFieldValue
		/// <summary>Set a property or field value</summary>
		/// <param name="obj">source object</param>
		/// <param name="member">property or field to set</param>
		/// <param name="value">value of the property or field</param>
		/// <returns>true if success, otherwise false</returns>
		public static bool SetPropertyOrFieldValue(object obj, string member, object value)
		{
			return SetPropertyOrFieldValue(obj, member, value, BF_ANY_PROP_FIELD);
		}
		/// <summary>Set a property or field value</summary>
		/// <param name="obj">source object</param>
		/// <param name="member">property or field to set</param>
		/// <param name="value">value of the property or field</param>
		/// <param name="flags">Binding flags</param>
		/// <returns>true if success, otherwise false</returns>
		public static bool SetPropertyOrFieldValue(object obj, string member, object value, BindingFlags flags)
		{
			// search a property with that name
			var prop = obj.GetType().GetProperty(member, flags);

			if (prop != null)
			{
				prop.SetValue(obj, value, null);

				return true;
			}

			// Property not found, try field
			var field = obj.GetType().GetField(member, flags);

			if (field != null)
			{
				field.SetValue(obj, value);

				return true;
			}

			return false;
		}
		#endregion

        #region GetPropertyInfo
        public static PropertyInfo GetPropertyInfo(object obj, string member)
        {
            return GetPropertyInfo(obj.GetType(), member, BF_ANY_PROP_FIELD);
        }
        public static PropertyInfo GetPropertyInfo(Type type, string member)
        {
            return GetPropertyInfo(type, member, BF_ANY_PROP_FIELD);
        }

        public static PropertyInfo GetPropertyInfo(object obj, string member, BindingFlags flags)
        {
            return GetPropertyInfo(obj.GetType(), member, flags);
        }

        public static PropertyInfo GetPropertyInfo(Type type, string member, BindingFlags flags)
        {
            return type.GetProperty(member, flags);
        }
        #endregion

		#region GetProperties
		public static PropertyInfo[] GetProperties(object obj)
		{
			var type = obj.GetType();

			return GetPropertiesForType(type);
		}
		public static PropertyInfo[] GetPropertiesForType(Type type)
		{
			return type.GetProperties(BF_ANY_PROP_FIELD);
		}
        public static PropertyInfo[] GetProperties(object obj, BindingFlags bindingFlags)
        {
            var type = obj.GetType();

            return GetPropertiesForType(type, bindingFlags);
        }
        
        public static PropertyInfo[] GetPropertiesForType(Type type, BindingFlags bindingFlags)
        {
            return type.GetProperties(bindingFlags);
        }
        #endregion

        #region GetPropertyAttribute
        //public static Attribute GetPropertyAttribute(Type type, Type desiredType, string propertyName)
        //{
        //    return GetPropertyAttribute(type, desiredType, propertyName, false);
        //}

        //public static Attribute GetPropertyAttribute(Type type, Type desiredType, string propertyName, bool inherit)
        //{
        //    try
        //    {
        //        var propertyInfo = GetPropertyInfo(type, propertyName);

        //        if (propertyInfo == null)
        //        {
        //            return null;
        //        }

        //        var result = propertyInfo.GetCustomAttributes(desiredType, inherit);

        //        if (Is.NotEmptyArray(result))
        //        {
        //            return (Attribute)result[0];
        //        }

        //        return null;
        //    }
        //    catch (Exception ex)
        //    {
        //        var newEx = new Exception("GetPropertyAttribute Failed", ex);

        //        newEx.Data.Add("Type", type);
        //        newEx.Data.Add("Desired Type", desiredType);

        //        throw newEx;
        //    }
        //}

        public static TType GetPropertyAttribute<TType>(Type type, TType desiredType, string propertyName)
        {
            return GetPropertyAttribute(type, desiredType, propertyName, false);
        }

        public static TType GetPropertyAttribute<TType>(Type type, TType desiredType, string propertyName, bool inherit)
        {
            try
            {
                var propertyInfo = GetPropertyInfo(type, propertyName);

                if (propertyInfo == null)
                {
                    return default(TType);
                }

                var result = propertyInfo.GetCustomAttributes(desiredType.GetType(), inherit);

                if (Is.NotEmptyArray(result))
                {
                    return (TType)result[0];
                }

                return default(TType);
            }
            catch (Exception ex)
            {
                var newEx = new Exception("GetPropertyAttribute Failed", ex);

                newEx.Data.Add("Type", type);
                newEx.Data.Add("Desired Type", desiredType);

                throw newEx;
            }
        }
        #endregion

		#region GetAttribute
		public static Attribute GetAttribute(Type type, Type desiredType)
		{
			return GetAttribute(type, desiredType, false);
		}

		public static Attribute GetAttribute(Type type, Type desiredType, bool inherit)
		{
			try
			{
				object[] result = type.GetCustomAttributes(desiredType, inherit);

				if (Is.NotEmptyArray(result))
				{
					return (Attribute)result[0];
				}

				return null;
			}
			catch (Exception ex)
			{
                var newEx = new Exception("GetAttribute Failed", ex);

                newEx.Data.Add("Type", type);
                newEx.Data.Add("Desired Type", desiredType);

                throw newEx; 
			}
		}
		#endregion

		#region GetAttributes
		public static object[] GetAttributes(Type type, Type desiredType)
		{
			return GetAttributes(type, desiredType, false);
		}

		public static object[] GetAttributes(Type type, Type desiredType, bool inherit)
		{
			try
			{
				return type.GetCustomAttributes(desiredType, inherit);
			}
			catch (Exception ex)
			{
                var newEx = new Exception("GetAttributes Failed", ex);

                newEx.Data.Add("Type", type);
                newEx.Data.Add("Desired Type", desiredType);

                throw newEx; 
			}
		}
		#endregion

	    // *********************************************************************************
	    // Run Methods
	    // *********************************************************************************

        #region RunInstanceMethodResult<TResult>
        public static TResult RunInstanceMethodResult<TResult>(object instance, string methodName, params object[] parameterValues)
        {
            return (TResult)RunMethodResult(BF_ANY_METHOD_INSTANCE, instance.GetType(), methodName, instance, parameterValues);
        }
        #endregion

        #region RunInstanceMethodResult
        public static object RunInstanceMethodResult(object instance, string methodName, params object[] parameterValues)
        {
            return RunMethodResult(BF_ANY_METHOD_INSTANCE, instance.GetType(), methodName, instance, parameterValues);
        }
        #endregion

        #region RunStaticMethodResult<TResult>
        public static TResult RunStaticMethodResult<TResult>(Type type, string methodName, params object[] parameterValues)
        {
            return (TResult)RunMethodResult(BF_ANY_METHOD_STATIC, type, methodName, null, parameterValues);
        }
        #endregion

        #region RunStaticMethodResult
        public static object RunStaticMethodResult(Type type, string methodName, object[] parameterValues)
        {
            return RunMethodResult(BF_ANY_METHOD_STATIC, type, methodName, null, parameterValues);
        }
        #endregion

        #region RunMethodResult
        private static object RunMethodResult(BindingFlags flags, Type t, string methodName, object instance, object[] parameterValues)
        {
            var methodInfo = t.GetMethod(methodName, flags);

            if (methodInfo == null)
            {
                throw new ArgumentException("There is no method '{0}' for type '{1}'".FormatWith(methodName, t));
            }

            var result = methodInfo.Invoke(instance, parameterValues);

            return result;
        }
        #endregion
    }

	#region Not Yet Tested but maybe Usefull Routines (LoadTypeInSeparateAppDomain)
	//    FROM RAZOR (TypeLoader)
	//		public static Type LoadTypeInSeparateAppDomain(string typename, string assemblyname)
	//		{
	//			try
	//			{
	//				/// first try loading the type the easy way
	//				Type t = Type.GetType(typename, false, true);
	//				if (t == null)
	//				{
	//					/// it didn't load, so try loading the reference and then finding it
	//					/// but do it in a separate app domain so that we don't incur the wrath of the overhead monkey
	//					AppDomain domain = AppDomain.CreateDomain(Guid.NewGuid().ToString());
	//					TypeLoader loader = (TypeLoader)domain.CreateInstanceFromAndUnwrap(System.Reflection.Assembly.GetExecutingAssembly().Location, typeof(TypeLoader).FullName);
	//					t = loader.LoadType(typename, assemblyname);
	//					AppDomain.Unload(domain);					
	//				}
	//				return t;
	//			}
	//			catch(System.Exception systemException)
	//			{
	//				System.Diagnostics.Trace.WriteLine(systemException);
	//			}
	//			return null;
	//		}
	#endregion
}
